#include <sys/syscalls.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <newos/drivers.h>
//#include "Renderer_vga.h"
#include "GraphicsContext.h"
#include "Window.h"
#include "WindowManager.h"
#include "Renderer_vesa.h"

using namespace os::gui;

#if 0

#define VENDOR 0x102b
#define DEVICE 0x051a

struct ColorMapEntry {
	int red;
	int green;
	int blue;
} colorTable[255] = {
	{0, 0, 0},
	{112, 219, 147},
	{112, 219, 147},
	{50, 204, 153},
	{50, 204, 153},
	{0, 0, 0},
	{0, 0, 0},
	{0, 0, 255},
	{0, 0, 255},
	{95, 159, 159},
	{95, 159, 159},
	{66, 66, 111},
	{66, 66, 111},
	{107, 35, 142},
	{107, 35, 142},
	{191, 216, 216},
	{191, 216, 216},
	{143, 143, 188},
	{143, 143, 188},
	{50, 50, 204},
	{50, 50, 204},
	{127, 0, 255},
	{127, 0, 255},
	{47, 47, 79},
	{47, 47, 79},
	{35, 35, 142},
	{35, 35, 142},
	{35, 35, 142},
	{35, 35, 142},
	{50, 153, 204},
	{50, 153, 204},
	{0, 127, 255},
	{0, 127, 255},
	{35, 107, 142},
	{35, 107, 142},
	{255, 127, 0},
	{255, 127, 0},
	{0, 255, 255},
	{0, 255, 255},
	{142, 35, 35},
	{142, 35, 35},
	{204, 127, 50},
	{204, 127, 50},
	{219, 219, 112},
	{219, 219, 112},
	{234, 234, 173},
	{234, 234, 173},
	{0, 255, 0},
	{0, 255, 0},
	{47, 79, 47},
	{47, 79, 47},
	{79, 79, 47},
	{79, 79, 47},
	{35, 142, 35},
	{35, 142, 35},
	{50, 204, 50},
	{50, 204, 50},
	{107, 142, 35},
	{107, 142, 35},
	{66, 111, 66},
	{66, 111, 66},
	{127, 255, 0},
	{127, 255, 0},
	{143, 188, 143},
	{143, 188, 143},
	{35, 142, 107},
	{35, 142, 107},
	{0, 255, 127},
	{0, 255, 127},
	{153, 204, 50},
	{153, 204, 50},
	{47, 79, 79},
	{47, 79, 79},
	{47, 79, 79},
	{47, 79, 79},
	{84, 84, 84},
	{84, 84, 84},
	{84, 84, 84},
	{84, 84, 84},
	{168, 168, 168},
	{168, 168, 168},
	{168, 168, 168},
	{168, 168, 168},
	{159, 159, 95},
	{159, 159, 95},
	{255, 0, 255},
	{255, 0, 255},
	{142, 35, 107},
	{142, 35, 107},
	{204, 50, 50},
	{204, 50, 50},
	{219, 112, 219},
	{219, 112, 219},
	{153, 50, 204},
	{153, 50, 204},
	{147, 112, 219},
	{147, 112, 219},
	{188, 143, 143},
	{188, 143, 143},
	{234, 173, 234},
	{234, 173, 234},
	{255, 0, 0},
	{255, 0, 0},
	{79, 47, 47},
	{79, 47, 47},
	{219, 112, 147},
	{219, 112, 147},
	{255, 0, 127},
	{255, 0, 127},
	{204, 50, 153},
	{204, 50, 153},
	{111, 66, 66},
	{111, 66, 66},
	{142, 107, 35},
	{142, 107, 35},
	{219, 147, 112},
	{219, 147, 112},
	{216, 191, 216},
	{216, 191, 216},
	{173, 234, 234},
	{173, 234, 234},
	{112, 147, 219},
	{112, 147, 219},
	{112, 219, 219},
	{112, 219, 219},
	{79, 47, 79},
	{79, 47, 79},
	{159, 95, 159},
	{159, 95, 159},
	{216, 216, 191},
	{216, 216, 191},
	{252, 252, 252},
	{252, 252, 252},
	{255, 255, 0},
	{255, 255, 0},
	{147, 219, 112},
	{147, 219, 112},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255},
	{255, 255, 255}		// Transparent color
};
#endif


#if 0
char *mga_find()
{
	uchar *fb;
	pci_cfg cfg;

	if(pci_find(&cfg,VENDOR,DEVICE)) return 0;
	fb = (uchar *) (cfg.base[0] & 0xfffffff0);
    if(area_create(0x100000, 0, (void**) &(fb), AREA_PHYSMAP) < 0){
        return 0;
    }
#if 1
        { int i;
                for(i=0;i<1024*768;i++) fb[i] = i / 3072;
        }
#endif
	return (char*) fb;
}

char *argv[] = { "/boot/www", "www", 0 };

int main()
{
//	InitVGA();
//	char *vmem = (char*) 0xa0000;
	char *vmem = mga_find();
	if(vmem == 0) return 1;

//	area_create(64*1024, 0, (void**) &vmem, AREA_PHYSMAP);
	memset((void*) vmem, 0, 1024 * 768);

	Renderer *screen = new Renderer_vga((char*) vmem, 1024, 768, 1024);
	for (int i = 0; i < 256; i++)
		SetPalette(i, colorTable[i].red, colorTable[i].green, colorTable[i].blue);

	new WindowManager(screen);
	os_sleep(1000000);
	execve(argv[0],argv,0);
	return 0;
}
#endif

int vesa_find(Renderer **renderer)
{
	int fd;
	devfs_framebuffer_info fb;
	int err;
	void *framebuffer;

	fd = open("/dev/graphics/vesa/fb/0", 0);
	if(fd < 0) {
		printf("error opening vesa device\n");
		return -1;
	}

	err = ioctl(fd, IOCTL_DEVFS_GET_FRAMEBUFFER_INFO, &fb, sizeof(fb));
	if(err < 0) {
		printf("error getting framebuffer info\n");
		return -2;
	}

	err = ioctl(fd, IOCTL_DEVFS_MAP_FRAMEBUFFER, &framebuffer, sizeof(framebuffer));
	if(err < 0) {
		printf("error mapping framebuffer\n");
		return -3;
	}

	switch(fb.color_space) {
		case COLOR_SPACE_RGB555:
			*renderer = new Renderer_vesa_555((char *)framebuffer, fb.width, fb.height, fb.width * 2);
			return 0;
		default:
			*renderer = 0;
			return -4;
	}
}


int main(int argc, char **argv)
{
	Renderer *screen;
	int err;

	err = vesa_find(&screen);
	if(err < 0) {
		printf("unable to find framebuffer\n");
		return err;
	}

/*
	Rect r = screen->Bounds();

	// clear the screen
	screen->FillRect(r, 0xffffffff);

	int i;

	for(i = 0; i < 256; i++) {
		screen->DrawLine(rand() % r.Width(), rand() % r.Height(), rand() % r.Width(), rand() % r.Height(), 0);
	}

	usleep(2000000);

	for(i = 0; i < 256; i++) {
		Rect source;
		Rect dest;

		usleep(10000);

		source.SetTo(rand() % r.Width(), rand() % r.Height(), rand() % r.Width(), rand() % r.Height());
		dest.SetTo(rand() % r.Width(), rand() % r.Height(), rand() % r.Width(), rand() % r.Height());
		screen->CopyRect(source, dest);
	}

	{
		Rect source(100, 100, 200, 200);
		Rect dest(150, 150, 250, 250);

		screen->CopyRect(source, dest);
	}

	usleep(1000000);

	{
		Rect source(300, 300, 400, 400);
		Rect dest(250, 250, 350, 350);

		screen->CopyRect(source, dest);
	}
*/
	WindowManager *wm = new WindowManager(screen);

	wm->WaitForExit();
	return 0;
}

